package com.kma.summer2012.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.kma.summer2012.client.ExceptionHandling.CrumbsRPCServiceException;
import com.kma.summer2012.client.services.request.CrumbsRequestService;
import com.kma.summer2012.dao.*;
import com.kma.summer2012.exceptions.CrumbsUniversalException;
import com.kma.summer2012.facade.RequestFacade;
import com.kma.summer2012.factory.DAOFactory;
import com.kma.summer2012.factory.SpringBeansFactory;
import com.kma.summer2012.model.*;
import com.kma.summer2012.server.proxy.Proxy;
import com.kma.summer2012.shared.model.*;

import java.sql.SQLException;
import java.util.*;

//import java.sql.SQLException;
//import java.text.SimpleDateFormat;

public class CrumbsRequestServiceImpl extends RemoteServiceServlet implements CrumbsRequestService {

    public Boolean saveComments(UIComment comment) throws CrumbsRPCServiceException {

        RequestFacade facade = SpringBeansFactory.getInstance().getBeanByClass(RequestFacade.class);
        try {
            return facade.saveProccessHistoryItem(comment.getCommenter().getUserId(), comment.getCommenter().getUserId(), comment.getrequestId(), comment.getComment(), comment.getCommentDate());

        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Saving of comments to DataBase failed.", e);
        }
    }

    public UICrumbsClient addNewClient(UICrumbsClient newClient) throws CrumbsRPCServiceException {

        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsClientDAO dao = (CrumbsClientDAO) factory.getCrumbsClientDAO();
        UICrumbsClient addedClient = new UICrumbsClient();
        try {
            addedClient = Proxy.getInstance().createFromClient(dao.addClient((CrumbsClient) Proxy.getInstance().createClient(newClient)));
        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Adding of a client to DataBase failed.", e);
        }

        return addedClient;
    }

    public UICrumbsRequest editOperatorRequest(UICrumbsRequest request) throws CrumbsRPCServiceException {

        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        UICrumbsRequest updatedRequest = new UICrumbsRequest();
        CrumbsRequestDAO dao = (CrumbsRequestDAO) factory.getCrumbsRequestDAO();

        try {
            CrumbsRequest uPrequest = (CrumbsRequest) factory.getCrumbsRequestDAO().getById(request.getId());

            uPrequest.setRequestInfo(request.getRequestInfo());
            CrumbsRequestAndWorkDAO workDAO = (CrumbsRequestAndWorkDAO) factory.getCrumbsRequestAndWorkDAO();
            Set<CrumbsRequestAndWork> set = new HashSet<CrumbsRequestAndWork>();
            for (UICrumbsWorkItem i : request.getUicrumbsWorkItems().keySet()) {
                CrumbsRequestAndWork newRequestAndWork = new CrumbsRequestAndWork();
                try {
                    newRequestAndWork.setCrumbsCatalogOfWork(factory.getCrumbsCatalogOfWorkDAO().getById(i.getId()));
                } catch (Exception e) {
                    throw new CrumbsRPCServiceException("Adding of work to DataBase failed.", e);
                }
                newRequestAndWork.setAmountOfWork(request.getUicrumbsWorkItems().get(i));
                newRequestAndWork.setCrumbsRequest(uPrequest);
                // workDAO.add(newRequestAndWork);
                boolean find = false;

                for (CrumbsRequestAndWork requestAndWork : uPrequest.getCrumbsRequestAndWorks()) {
                    if (requestAndWork.getCrumbsCatalogOfWork().getId() == newRequestAndWork.getCrumbsCatalogOfWork().getId()) {
                        find = true;
                        requestAndWork.setAmountOfWork(newRequestAndWork.getAmountOfWork());
                        workDAO.update(requestAndWork);
                        set.add(requestAndWork);
                    }
                }
                if (!find) {
                    set.add(workDAO.addWithReturn(newRequestAndWork));
                }
            }
            for (CrumbsRequestAndWork requestAndWork : uPrequest.getCrumbsRequestAndWorks()) {
                boolean find = false;
                for (CrumbsRequestAndWork setReq : set) {
                    if (setReq.getId() == requestAndWork.getId()) {
                        find = true;
                    }
                }
                if (!find) {
                    workDAO.delete(requestAndWork);
                }
            }
            if (uPrequest.getCrumbsRequestsState().getId() == 5) {
                uPrequest.setCrumbsRequestsState(factory.getCrumbsRequestsStateDAO().getById(1));
            }

            factory.getCrumbsRequestDAO().update(uPrequest);
            updatedRequest = Proxy.getInstance().createFromRequest(factory.getCrumbsRequestDAO().getById(request.getId()));
            return updatedRequest;

        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Error in connection to database.", e);
        }


    }

    public Boolean editManagerRequest(int request_id) throws CrumbsRPCServiceException {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        try {
            CrumbsRequest request = factory.getCrumbsRequestDAO().getById(request_id);
            if (request.getCrumbsRequestsState().getId() == 4) {
                request.setCrumbsRequestsState(factory.getCrumbsRequestsStateDAO().getById(2));
                factory.getCrumbsRequestDAO().update(request);

            }

        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Updating of the request failed.", e);
        }
        return true;
    }


    public UICrumbsClient updateClient(UICrumbsClient client) throws CrumbsRPCServiceException {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsClientDAO daoClient = (CrumbsClientDAO) factory.getCrumbsClientDAO();

        UICrumbsClient updatedClient = new UICrumbsClient();
        try {
            daoClient.update(Proxy.getInstance().createClient(client));
            updatedClient = Proxy.getInstance().createFromClient(daoClient.getById(client.getId()));

        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Updating of the client failed.", e);
        }
        return updatedClient;
    }


    //public void addNewRequest(UICrumbsRequest newRequest) {
    public UICrumbsRequest addNewRequest(UICrumbsRequest newRequest) throws CrumbsRPCServiceException {


        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsRequestDAO dao = (CrumbsRequestDAO) factory.getCrumbsRequestDAO();
        CrumbsRequest addedRequest = new CrumbsRequest();
        UICrumbsRequest result = new UICrumbsRequest();
        try {
            addedRequest = dao.addRequest(Proxy.getInstance().createRequest(newRequest));
            result = Proxy.getInstance().createFromRequest(addedRequest);

        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Adding of the request to DataBase failed.", e);
        }

        CrumbsRequestAndWorkDAO workDAO = (CrumbsRequestAndWorkDAO) factory.getCrumbsRequestAndWorkDAO();
        for (UICrumbsWorkItem i : newRequest.getUicrumbsWorkItems().keySet()) {
            CrumbsRequestAndWork newRequestAndWork = new CrumbsRequestAndWork();
            try {
                newRequestAndWork.setCrumbsCatalogOfWork(factory.getCrumbsCatalogOfWorkDAO().getById(i.getId()));
                newRequestAndWork.setAmountOfWork(newRequest.getUicrumbsWorkItems().get(i));
                newRequestAndWork.setCrumbsRequest(addedRequest);
                workDAO.add(newRequestAndWork);

            } catch (Exception e) {
                throw new CrumbsRPCServiceException("Adding of workSet to the request failed.", e);  //To change body of catch statement use File | Settings | File Templates.
            }

        }
        return result;


    }

    public Integer saveDate(int requestID, Date start, Date end) throws CrumbsRPCServiceException {

        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsDateAndTimeDAO datedao = (CrumbsDateAndTimeDAO) factory.getCrumbsDateAndTimeDAO();
        CrumbsDateAndTime newdateItem = new CrumbsDateAndTime();
        try {
            CrumbsRequest request = (CrumbsRequest) factory.getCrumbsRequestDAO().getById(requestID);
            newdateItem.setCrumbsRequest(request);
            newdateItem.setDateBegin(start);
            newdateItem.setDateEnd(end);
            datedao.addDate(newdateItem);
            //         return newdateItem.getId();
        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Saving of the date to DataBase failed.", e);
        }
        //todo
        //????? Чи треба ця перевірка?
        if (newdateItem == null)
            return -1;
        return newdateItem.getId();
        //    return -1;
    }

    public Integer updateDate(int requestID, Date start, Date end) throws CrumbsRPCServiceException {

        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsDateAndTimeDAO datedao = (CrumbsDateAndTimeDAO) factory.getCrumbsDateAndTimeDAO();
        try {

            CrumbsRequest req = (CrumbsRequest) factory.getCrumbsRequestDAO().getById(requestID);
            CrumbsDateAndTime updateDate = new CrumbsDateAndTime();
            int index = 0;
            for (Object t : req.getCrumbsDateAndTimes()) {
                if (index == 0) {

                    updateDate = (CrumbsDateAndTime) t;

                } else break;
            }
            ;

            updateDate.setDateBegin(start);
            updateDate.setDateEnd(end);

            datedao.update(updateDate);
            return 1;
        } catch (Exception e) {
            //todo
            throw new CrumbsRPCServiceException("Updating of the date failed.", e);
        }
    }

    @Override
    public List<UICrumbsRequest> getAllRequests() throws CrumbsRPCServiceException {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsRequestDAO dao = (CrumbsRequestDAO) factory.getCrumbsRequestDAO();
        List<UICrumbsRequest> uilist = new ArrayList<UICrumbsRequest>();
        try {
            Collection<CrumbsRequest> list = dao.getAll();
            for (CrumbsRequest crumbsRequest : list) {
                uilist.add(Proxy.getInstance().createFromRequest(crumbsRequest));
            }
        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Getting of the list of requests from DataBase failed.", e);
        }
        return uilist;

    }

    @Override
    public Boolean sendchangeState(int id, String comment, int senderId) throws CrumbsRPCServiceException {
        RequestFacade facade = SpringBeansFactory.getInstance().getBeanByClass(RequestFacade.class);
        try {
            facade.changeState(id, comment, senderId);
            return true;
        } catch (Exception e) {
            //todo Should we process it differently from CrumbsUniversalException?
            throw new CrumbsRPCServiceException("Changing of request state failed.", e);
        }
    }

    public UICrumbsRequest getById(int id) {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        try {
            CrumbsRequest request = factory.getCrumbsRequestDAO().getById(id);
            if (request != null) {
                return Proxy.getInstance().createFromRequest(request);
            } else return null;
        } catch (Exception e) {
            throw new CrumbsUniversalException("Getting of Request from DataBase failed.", e);
        }
    }


    @Override
    public Boolean assignRequest(int user_id, int request_id, Date assignDateBegin, Date assignDateEnd) throws CrumbsRPCServiceException {
        RequestFacade facade = SpringBeansFactory.getInstance().getBeanByClass(RequestFacade.class);
        try {
            return facade.assignRequest(user_id, request_id, assignDateBegin, assignDateEnd);
        } catch (Exception e) {
            System.out.println(e);
            throw new CrumbsRPCServiceException("Assigning of the request failed.", e);
        }
    }

    @Override
    public Boolean getHistoryForRequest(int requestID, int commenterID) throws CrumbsRPCServiceException {

        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsProcessHistoryDAO history = (CrumbsProcessHistoryDAO) factory.getCrumbsProcessHistoryDAO();
        try {

            history.getHistoryForRequest(requestID, commenterID);
            return true;

        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Unable to close request - facade error", e);

        }

    }

    public UICrumbsRequest getLastCommentFromManger(UICrumbsRequest request) throws CrumbsRPCServiceException {
        RequestFacade facade = SpringBeansFactory.getInstance().getBeanByClass(RequestFacade.class);


        try {
            if (facade.lastCommentFromMamager(request.getId()) != null) {

                request = Proxy.getInstance().createFromRequest(facade.lastCommentFromMamager(request.getId()));
            }
            return request;
            //TODO please use code formating!!! CTRL+Atl+L!!!!!!!

        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Getting of the comment from DataBase filed. ", e);
        }
    }
    @Override
    public Boolean closeRequest(Map<UICrumbsToolItem, Integer> actualToolsAndAmount, UICrumbsRequest request, String comment, int userId, String date) throws CrumbsRPCServiceException {
        RequestFacade facade = SpringBeansFactory.getInstance().getBeanByClass(RequestFacade.class);


        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        try {
            CrumbsRequest updateRequest = factory.getCrumbsRequestDAO().getById(request.getId());
            updateRequest.setActualTimeOfWork(request.getActualTimeOfWork());
            updateRequest.setCrumbsRequestsState(factory.getCrumbsRequestsStateDAO().getById(6));
            factory.getCrumbsRequestDAO().update(updateRequest);
            facade.saveProccessHistoryItem(userId, userId, request.getId(), comment, date);
            Map<CrumbsCatalogOfTools, Integer> actualToolsAndAmountdb = new HashMap<CrumbsCatalogOfTools, Integer>();
            for (UICrumbsToolItem key : actualToolsAndAmount.keySet()) {
                actualToolsAndAmountdb.put(factory.getCrumbsCatalogOfToolsDAO().getById(key.getId()), actualToolsAndAmount.get(key));
            }
            return facade.closeRequest(updateRequest, actualToolsAndAmountdb);
        } catch (Exception e) {
            //todo Should we process it differently
            throw new CrumbsRPCServiceException("Closing of the request failed.", e);
        }

    }

    @Override
    public Boolean sendForProcessing(int idSender, int idRequest) throws CrumbsRPCServiceException {

        RequestFacade facade = SpringBeansFactory.getInstance().getBeanByClass(RequestFacade.class);
        try {
            return facade.sendForProcessing(idSender, idRequest);
        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Sending request for processing failed.", e);
        }
    }
    @Override
    public UICrumbsRequest initialize(UICrumbsRequest request) throws CrumbsRPCServiceException {

        RequestFacade facade = SpringBeansFactory.getInstance().getBeanByClass(RequestFacade.class);
        CrumbsRequest res = null;
        try {
            res = facade.initializeAdditioools(request.getId());
            if (res != null) {
                for (CrumbsAdditionalTools tool : res.getCrumbsAdditionalTools()) {
                    UICrumbsToolItem additionalTool = new UICrumbsToolItem();
                    additionalTool.setId(tool.getId());
                    additionalTool.setToolName(tool.getCrumbsCatalogOfTools().getName());
                    additionalTool.setToolsDescription(tool.getCrumbsCatalogOfTools().getToolsDescription());
                    request.getUicrumbsToolsItems().put(additionalTool, (short) tool.getAmount());
                }
            }
        } catch (Exception e) {
            //todo process differently?
            throw new CrumbsRPCServiceException("Initialization of request's additionTools failed.", e);


        }
        return request;
    }
    @Override
    public Boolean sendAllForProcessing(int idSender, List<UICrumbsRequest> requests) throws CrumbsRPCServiceException {
        RequestFacade facade = SpringBeansFactory.getInstance().getBeanByClass(RequestFacade.class);
        try {
            boolean res = true;
            for (UICrumbsRequest request : requests) {
                res = facade.sendForProcessing(idSender, request.getId());
                if (!res) {  //TODO  why '==' ? in the chat we discus
                    return false;
                }
            }
            return res;

        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Sending requests for processing from operator failed.", e);
        }

    }


    public List<UICrumbsRequest> getAllForUser(UICrumbsUser user) throws CrumbsRPCServiceException {
        CrumbsUser crumbsUser = Proxy.getInstance().createUser(user);

        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsRequestDAO dao = (CrumbsRequestDAO) factory.getCrumbsRequestDAO();
        List<UICrumbsRequest> uilist = new ArrayList<UICrumbsRequest>();
        try {
            Collection<CrumbsRequest> list = dao.getAllForUser(crumbsUser);
            //List<UICrumbsRequest> uilist = new ArrayList<UICrumbsRequest>();
            if (list != null) {
                for (CrumbsRequest crumbsRequest : list) {
                    uilist.add(Proxy.getInstance().createFromRequest(crumbsRequest));
                }

            }

        } catch (Exception e) {   //TODO  bad bad bad exception catching
            throw new CrumbsRPCServiceException("Getting the list of requests for user failed.", e);
        }
        return uilist;
    }

    @Override
    public List<UICrumbsRequest> getAllClosed() throws CrumbsRPCServiceException {
        DAOFactory factory = SpringBeansFactory.getInstance().getBeanByClass(DAOFactory.class);
        CrumbsRequestDAO dao = (CrumbsRequestDAO) factory.getCrumbsRequestDAO();
        try {
            Collection<CrumbsRequest> list = dao.getAllClosed();
            List<UICrumbsRequest> uilist = new ArrayList<UICrumbsRequest>();
            for (CrumbsRequest crumbsRequest : list) {
                uilist.add(Proxy.getInstance().createFromRequest(crumbsRequest));
            }
            return uilist;
        } catch (Exception e) {  //TODO  bad bad bad exception catching
            //todo
            throw new CrumbsRPCServiceException("Getting the list of all closed requests failed.", e);
        }
    }



    @Override
    public Boolean deleteRequests(List<Integer> requests) throws CrumbsRPCServiceException {
        RequestFacade facade = SpringBeansFactory.getInstance().getBeanByClass(RequestFacade.class);
        try {
            return facade.deleteRequests(requests);

        } catch (Exception e) {
            throw new CrumbsRPCServiceException("Deletion of the requests from DataBase failed.", e);
        }
    }
    


}
